<?php
namespace app\manage\model;
use think\Db;

class RebatedOrder extends Base
{
    /*
 * 获取已日期和规则id为键的订单数组,并计算出返利值
 */
    function getRebateData($gameId,$myUserName,$myOrderId,$roleId,$roleName,$startDate,$endDate)
    {

        $sYear=date('Y',$startDate);
        $eYear=date('Y',$endDate);
        $fields = "my_order_id,channel_id,reg_cps_id,game_id,my_user_id,my_user_name,pay_time,";
        $fields.="total_price/100 as total_price,ratio,server_id,server_name,role_id,";
        $fields.="role_name,coin,rebate_time,ext";
        $sort = 'pay_time desc';
        //$where['rebate_time']=0;
        if($myOrderId!=''){
            $table = get_order_table($myOrderId);
            $order = Db::name($table)
                ->where(['my_order_id'=>$myOrderId])
                ->find();
            if(empty($order)) return [];

            $where['channel_id'] = $order['channel_id'];
            $where['cps_id'] = $order['cps_id'];
            $where['my_user_id'] = $order['my_user_id'];
            $where['game_id'] = $order['game_id'];
            $where['server_id'] = $order['server_id'];
            $where['role_id'] = $order['role_id'];
        }elseif($myUserName!='' && $gameId!=''){
            $where['channel_id'] = 1000;
            $where['my_user_name'] = $myUserName;
            $where['game_id'] = $gameId;
        }elseif($gameId!=''&&$roleId!=''){
            $where['game_id'] = $gameId;
            $where['role_id'] = $roleId;
        }elseif($gameId!=''&&$roleName!=''){
            $where['game_id'] = $gameId;
            $where['role_name'] = $roleName;
        }else{
            return [];
        }

        if($sYear<$eYear){
            if($eYear-$sYear>1){
                $sYear=$eYear-1;//年跨度不能超过2年
            }
            $midDate=strtotime($eYear.'0101');
            $table='pay_order_y_'.$sYear;
            $payStatus="((pay_time>=$startDate and pay_time<=$midDate) or debug=1)";
            $payOrderData1 = Db::name($table)
                ->field($fields)
                ->where($where)
                ->where($payStatus)
                ->order($sort)
                ->select();

            $table='pay_order_y_'.$eYear;
            $payStatus="((pay_time>=$midDate and pay_time<=$endDate) or debug=1)";
            $payOrderData2 = Db::name($table)
                ->field($fields)
                ->where($where)
                ->where($payStatus)
                ->order($sort)
                ->select();
            $payOrderData=array_merge($payOrderData1,$payOrderData2);
            //logtofile('debug',M($table)->getLastSql());

        }else{
            $table='PayOrderY_'.$eYear;
            $payStatus="((pay_time>=$startDate and pay_time<=$endDate) or debug=1)";
            $payOrderData = Db::name($table)
                ->field($fields)
                ->where($where)
                ->where($payStatus)
                ->order($sort)
                ->select();
        }

        if(!empty($payOrderData)){
            $channelId = $payOrderData[0]['channel_id'];
            $myUserName = $payOrderData[0]['my_user_name'];
            if($channelId>1000){
                $myUserName='';
            }
            $myUserId = $payOrderData[0]['my_user_id'];
            $cpsId = $payOrderData[0]['reg_cps_id'];
        }else{
            return [];
        }

        //获取已返利的订单列表
        if($myUserName!=''){
            $where_rebated['loginname']=$myUserName;
        }else{
            $where_rebated['userid']=$myUserId;
        }

        $where_rebated['channelid'] = $channelId.'_'.$cpsId;
        $where_rebated['paytime'] = ['lt',$endDate];
        $where_rebated['paytime'] = ['egt',$startDate];
        $rebatedOrder = Db::name('RebatedOrder')->where($where_rebated)->select();
        $rebatedOrderArr=[];
        foreach ($rebatedOrder as $v) {
            if(isset($rebatedOrderArr[$v['gameid']][$v['serverid']][$v['roleid']][date('Y-m-d', $v['paytime'])][$v['orderid']])){
                $rebatedOrderArr[$v['gameid']][$v['serverid']][$v['roleid']][date('Y-m-d', $v['paytime'])][$v['orderid']] += $v['rebate_gamecoin'];
            }else{
                $rebatedOrderArr[$v['gameid']][$v['serverid']][$v['roleid']][date('Y-m-d', $v['paytime'])][$v['orderid']] = $v['rebate_gamecoin'];
            }

        }

        //全部规则
        $ruleAll = $this->getRuleAll();

        $serverArr = [];
        $roleArr = [];
        $userId=0;
        $gameDayOrderArr = [];
        $ruleArr = [];
        $myUserId='';
        foreach ($payOrderData as $v) {
            if(empty($myUserId)){
                if($v['my_user_id']<=45000000){
                    $rs=Db::name('User')->where(['my_user_id'=>$v['my_user_id'],'channel_id'=>$v['channel_id']])->find();
                    $myUserId=$rs['sdkdrive_id'];
                }
            }
            $gameId=$v['game_id'];
            if($gameId==1152){//1152的区服放在ext里
                $ext=json_decode($v['ext'],true);
                $v['server_id']=$ext['sid'];
            }

            //获取规则,不同权重分组
            if(!isset($ruleArr[$gameId])){
                //$ruleArr[$gameId]=$this->getGameRule($gameId, $startDate, $endDate,$v['pay_time']);
                //$ruleArr[$gameId]=$this->getRuleForOrder($gameId,$v['pay_time']);
            }
            $rebateRuleArr = $this->getRuleForOrder($gameId,$v['pay_time']);//$ruleArr[$gameId];

            empty($serverArr[$v['server_id']]) && $serverArr[$v['server_id']]=$v['server_name'];
            empty($roleArr[$v['role_id']]) && $roleArr[$v['role_id']]=$v['role_name'];
            $userId===0 && $userId=$v['my_user_id'];

            $order = array(
                'orderid' => $v['my_order_id'],
                'channelid' => $v['channel_id'].'_'.$v['reg_cps_id'],
                'gameid'=>$v['game_id'],
                'serverid'=>$v['server_id'],
                'servername'=>$v['server_name'],
                'userid' => empty($myUserId)?$v['my_user_id']:$myUserId,
                'loginname'=>$myUserName,
                'roleid' => $v['role_id'],
                'rolename'=>$v['role_name'],
                'amount' => $v['total_price'],
                'ratio' => $v['ratio'],
                'gamecoin' => $v['coin'],
                'paytime' =>$v['pay_time'],
                'isrebate'=>$v['rebate_time']>0?1:0,
                'ruleid'=>0,
                'rule'=>'',
                'rebate_gamecoin'=>0,
                'applyid'=>0,
                'applytime'=>0,
            );

            $gid = $v['game_id'];
            $gid=='' && $gid='_';
            $sid = $v['server_id'];
            $sid=='' && $sid='_';
            $rid = $v['role_id'];
            $rid=='' && $rid='_';
            $date = date('Y-m-d', $v['pay_time']);
            $date=='' && $date='_';
            $findRule = false;
            if (isset($rebateRuleArr['specRule'])) {//活动规则,可能有多条
                $specRuleArr = $rebateRuleArr['specRule'];
                foreach ($specRuleArr as $s) {
                    if ($v['pay_time'] >= $s['starttime'] && $v['pay_time'] <= $s['endtime']) {
                        $ruleid=$s['id'];
                        $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['order'][] = $order;
                        if (isset($gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['sum']['total_amount'])) {//按规则汇总
                            $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['sum']['total_amount'] += $v['total_price'];
                        } else {
                            $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['sum']['total_amount'] = $v['total_price'];
                        }
                        if (isset($gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['total_amount'])) {//按日期汇总
                            $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['total_amount'] += $v['total_price'];
                        } else {
                            $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['total_amount'] = $v['total_price'];
                        }
                        $findRule = true;
                        break;
                    }
                }
            }
            if(!$findRule){
                if (isset($rebateRuleArr['generalRule'])) {
                    $generalRuleArr = $rebateRuleArr['generalRule'];
                    $ruleid = $generalRuleArr['id'];
                    if ($v['pay_time']>=$generalRuleArr['starttime'] && $v['pay_time']<=$generalRuleArr['endtime']) {
                        $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['order'][] = $order;
                        if (isset($gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['sum']['total_amount'])) {//按规则汇总
                            $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['sum']['total_amount'] += $v['total_price'];
                        } else {
                            $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['sum']['total_amount'] = $v['total_price'];
                        }
                        if (isset($gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['total_amount'])) {//按日期汇总
                            $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['total_amount'] += $v['total_price'];
                        } else {
                            $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['total_amount'] = $v['total_price'];
                        }
                    } else {
                        $gameDayOrderArr[$gid][$sid][$rid][$date]['rule']['nonerule']['order'][] = $order;
                    }
                } else {
                    //无规则
                    $gameDayOrderArr[$gid][$sid][$rid][$date]['nonerule']['rule']['nonerule']['order'][] = $order;
                }
            }

        }

        //使用缓存,避免重复查询
//        cache(['type'=>'Redis']);
        cache(['type'=>'Memcache']);
        foreach ($gameDayOrderArr as $gid=>$game) {
            foreach ($game as $sid=>$role) {
                foreach($role as $rid=>$rule) {
                    foreach ($rule as $date => $date_rule) {
                        $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['rebateable_gamecoin'] = 0;//日期汇总,可返总额
                        $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['rebated_gamecoin'] = 0;//日期汇总,已返利
                        $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['toberebate_gamecoin'] = 0;//日期汇总,待返利等于上两个数的差
                        foreach($date_rule['rule'] as $ruleid=>$order){
                            $cur_order = $order['order'];
                            if($ruleid=='nonerule'){
                                foreach($cur_order as $k_nr=>$nr){
                                    $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['order'][$k_nr]['rule'] = '无规则';
                                }
                                continue;
                            }
                            $cur_rule = $this->getRuleById($ruleAll, $ruleid, $order['sum']['total_amount']);


                            $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['sum']['rebateable_gamecoin']=0;//规则汇总,可返总额

                            foreach ($cur_order as  $k_order=>$o) {
                                $rebate_gamecoin = $o['amount'] * ($o['ratio'] * $cur_rule['ratio']);
                                //订单返利计算
                                $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['order'][$k_order]['rule'] = $cur_rule['desc'];
                                $rebated=isset($rebatedOrderArr[$gid][$sid][$rid][$date][$o['orderid']])?$rebatedOrderArr[$gid][$sid][$rid][$date][$o['orderid']]:0;
                                $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['order'][$k_order]['rebate_gamecoin'] =
                                    $rebate_gamecoin-$rebated;
                                if(isset($rebatedOrderArr[$gid][$sid][$rid][$date][$o['orderid']])){
                                    $rebated_gamecoin=$rebatedOrderArr[$gid][$sid][$rid][$date][$o['orderid']];
                                }else{
                                    $rebated_gamecoin=0;
                                }
                                //按返利规则汇总
                                $gameDayOrderArr[$gid][$sid][$rid][$date]['rule'][$ruleid]['sum']['rebateable_gamecoin'] += $rebate_gamecoin;
                                //按日期汇总
                                $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['rebateable_gamecoin'] += $rebate_gamecoin;//应返
                                $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['rebated_gamecoin'] += $rebated_gamecoin;//已返
                                //按日期待返
                                $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['toberebate_gamecoin']=
                                    $gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['rebateable_gamecoin']-$gameDayOrderArr[$gid][$sid][$rid][$date]['sum']['rebated_gamecoin'];
                            }

                        }

                        //使用缓存,避免重复查询
                        if(!empty($myUserId)){//前面换了用户id,这里换回来,避免从缓存取出时转换id
                            $userId=$myUserId;
                        }
                        $cache_key='rebate_day_'.strtoupper(md5($userId.$gid.$sid.$rid.$date));
                        cache($cache_key, NULL);
                        cache($cache_key, $gameDayOrderArr[$gid][$sid][$rid][$date], 300);
                    }
                }
            }


        }

        //服务器名和角色名缓存,避免读库
        $cache_key='rebate_serverName_'.strtoupper(md5($userId.$startDate.$endDate));
        cache($cache_key, $serverArr, 600);
        $cache_key='rebate_roleName_'.strtoupper(md5($userId.$startDate.$endDate));
        cache($cache_key, $roleArr, 600);

        return $gameDayOrderArr;

    }

    private function getRuleAll(){
        $rule = Db::name('RebateRule')->select();
        $ret = [];
        foreach($rule as $v){
            $ret[$v['id']] = $v;
        }
        return $ret;
    }

    /**
     * 获取订单可用的规则
     */
    private function getRuleForOrder($gameId,$paytime){
        $rule = [];

        //白名单规则,特殊游戏规则,不限时间
        $where = "gamelist like '%$gameId%' and type=1 and starttime<=$paytime and endtime>=$paytime";
        $generalRule = Db::name('RebateRule')->where($where)->select();
        if($generalRule){
            $rule['generalRule'] = [
                'id' => $generalRule[0]['id'],
                'rule' => $generalRule[0]['rule'],
                'name' => $generalRule[0]['name'],
                'addtime' => $generalRule[0]['addtime'],
                'starttime' => $generalRule[0]['starttime'],
                'endtime' => $generalRule[0]['endtime'],
                'priority' => $generalRule[0]['priority'],
            ];
        }else{
            //通用规则,不限时间
            $generalRule = Db::name('RebateRule')->where(['type'=>0])->select();
            if($generalRule){
                $rule['generalRule'] = [
                    'id' => $generalRule[0]['id'],
                    'rule' => $generalRule[0]['rule'],
                    'name' => $generalRule[0]['name'],
                    'addtime' => $generalRule[0]['addtime'],
                    'starttime' => $generalRule[0]['starttime'],
                    'endtime' => $generalRule[0]['endtime'],
                    'priority' => $generalRule[0]['priority'],
                ];
            }
        }

        //黑名单规则,活动规则,名单内的游戏不参与
        $where = "type=2 and gamelist not like '%$gameId%' and starttime<=$paytime and endtime>=$paytime";
        $specRule = Db::name('RebateRule')->where($where)->select();
        if($specRule){
            $rule_pro = [];
            foreach($specRule as $w){
                $rule_pro[$w['id']] = [
                    'id' => $w['id'],
                    'rule' => $w['rule'],
                    'name' => $w['name'],
                    'addtime' => $w['addtime'],
                    'starttime' => $w['starttime'],
                    'endtime' => $w['endtime'],
                    'priority' => $w['priority'],
                ];
            }
            //按照权重降序,只匹配最先查到的规则
            $tmp_rule = array_sort($rule_pro, 'priority', 0);

            $rule['specRule'] = $tmp_rule;
        }

        return $rule;
    }

    /*
     * 通过规则id和金额获取比例
     */
    private function getRuleById($ruleArr,$id,$amount){
        $ret = ['ratio'=>0,'desc'=>''];
        if(isset($ruleArr[$id])){
            $ruleStr = $this->_ruleStrToArray($ruleArr[$id]['rule']);
            foreach($ruleStr as $v){
                if( $amount>=$v['min'] && $amount<=$v['max'] ){//两端包含
                    $ret = ['ratio'=>$v['ratio'],'desc'=>$v['desc']];
                    break;
                }
            }

        }else{
            $ret= ['ratio'=>0,'desc'=>''];
        }
        return $ret;
    }

    /*
     * 将字符串格式的返利规则转换成数组，并按照由低到高的顺序排列
     */
    private function _ruleStrToArray($ruleStr){
        $res_arr = [];
        $arr = explode(":",$ruleStr);
        if($arr) {
            foreach ($arr as $item) {
                $item = ltrim($item, "{");
                $item = rtrim($item, "}");
                $item = trim($item);
                if ($item != '') {
                    list($min, $max, $ratio, $desc) = explode(",", $item);
                    $res_arr[$min] = [
                        'min' => $min,
                        'max' => $max,
                        'ratio' => $ratio,
                        'desc' => $desc
                    ];
                }
            }
            ksort($res_arr);
        }
        return $res_arr;
    }

    //发送返利信息给游戏方
    public function sendGameInfo($params){
        ksort($params);
        $string = '';

        foreach($params as $key=>$value){
            $string .= $key . "=" . $value . "&";
        }
        $signString = substr($string, 0, -1);

        $game_row = model('ViewGameManage')->where('game_id', $params['gameid'])->field('secret,rebate_callback')->find();

        if(empty($game_row)) {
            $res['result'] = 0;
            $res['msg'] = '数据异常，不存在该游戏';
            return $res;
        }else if(empty($game_row['rebate_callback'])){
            $res['result'] = 0;
            $res['msg'] = '该游戏没有返利地址';
            return $res;
        }

        $signString="{$signString}:{$game_row['secret']}";
        $params['sign'] = md5($signString);

        if($params['gameid']==1152){
            $orderList = json_decode(urldecode($params['order_lists']),true);
            $orderId = $orderList[0];

            $where['my_order_id'] = $orderId;
            $table = get_order_table($orderId);
            $orderData = Db::name($table)->where($where)->field('ext')->find();
            $ext = json_decode($orderData['ext'],true);
            $game_row['rebate_url'] = $ext['url'].'/charge/miyurebate';
        }

        if($params['gameid']==1201 || $params['gameid']==1220){
            $orderList = json_decode(urldecode($params['order_lists']),true);
            $orderId = $orderList[0];

            $where['my_order_id'] = $orderId;
            $table = get_order_table($orderId);
            $orderData = Db::name($table)->where($where)->field('ext')->find();
            if($orderData){
                $ext = $orderData['ext'];
            }else{
                $ext = '';
            }
            $params['ext']=$ext;

        }


        if(config('local_debug')){
            $apply = json_encode(['result'=>1, 'msg'=>'请求成功']);
        }else{
            $apply= http($game_row['rebate_callback'],$params,'POST',array("Content-type: text/html; charset=utf-8"));
            $log='url:'.$game_row['rebate_callback'].'|params:'.json_encode($params).'|signStr:'.$signString.'|result:'.$apply;
            \think\Log::write($log,"rebate_log");
        }

        $res_game=json_decode($apply,true);



        if(is_array($res_game)){
            if(isset($res_game['result'])){
                if ($res_game['result'] != 1) {
                    $res['result'] = 0;
                    $res['msg'] = $res_game['msg'];
                }else{
                    $res['result'] = 1;
                    $res['msg'] = '审核通过';
                }
            }else{
                $res['result'] = -1;
                $res['msg'] = '游戏返回参数错误';
            }
        }else{
            $res['result'] = -1;
            $res['msg'] = '接口返回异常:'.$res_game;
        }
        return $res;
    }
}